package com.aizuda.boot.modules.business.contract_operation_log.service.impl;

import com.aizuda.boot.modules.business.contract_operation_log.domain.entity.ContractOperationLog;
import com.aizuda.boot.modules.common.constant.enums.WorkFlowTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.ActionTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.SourceTypeEnums;
import com.aizuda.boot.modules.business.contract_operation_log.domain.vo.ContractOperationLogRespDTO;
import com.aizuda.boot.modules.business.contract_operation_log.mapper.ContractOperationLogMapper;
import com.aizuda.boot.modules.business.contract_operation_log.service.ContractOperationLogService;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationNodeInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationParticipantEntity;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationNodeInstanceMapper;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationParticipantMapper;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationInstanceMapper;
import com.aizuda.boot.modules.file.domain.vo.FileVO;
import com.aizuda.boot.modules.file.service.FileInfoService;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 合同操作日志服务实现类
 */
@Slf4j
@Service
public class ContractOperationLogServiceImpl extends ServiceImpl<ContractOperationLogMapper, ContractOperationLog> implements ContractOperationLogService {
    
    @Resource
    private ContractNegotiationNodeInstanceMapper nodeInstanceMapper;
    
    @Resource
    private ContractNegotiationParticipantMapper participantMapper;
    
    @Resource
    private ContractNegotiationInstanceMapper instanceMapper;
    
    @Resource
    private ISysUserService sysUserService;
    
    @Resource
    private FileInfoService fileInfoService;
    
    @Override
    public List<ContractOperationLogRespDTO> getNegotiationLogs(Integer contractId, String flowType) {
        try {
            // 查询操作日志
            List<ContractOperationLog> logs = list(new LambdaQueryWrapper<ContractOperationLog>()
                    .eq(ContractOperationLog::getContractId, contractId.longValue())
                    .eq(ContractOperationLog::getFlowType, flowType)
                    .orderByAsc(ContractOperationLog::getActionTime));
            
            // 转换为响应DTO
            return logs.stream().map(this::convertToRespDTO).collect(Collectors.toList());
            
        } catch (Exception e) {
            log.error("获取协商日志失败，合同ID: {}, 流程类型: {}", contractId, flowType, e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 转换为响应DTO
     */
    private ContractOperationLogRespDTO convertToRespDTO(ContractOperationLog log) {
        ContractOperationLogRespDTO dto = new ContractOperationLogRespDTO();
        dto.setId(log.getId());
        dto.setContractId(log.getContractId());
        dto.setActionTime(log.getActionTime());
        dto.setRemark(log.getRemark());
        
        // 设置流程类型
        setFlowTypeInfo(dto, log.getFlowType());
        
        // 设置操作类型
        setActionTypeInfo(dto, log.getActionType());
        
        // 设置数据源类型
        setSourceTypeInfo(dto, log.getSourceType());
        
        // 设置操作人信息
        setOperatorInfo(dto, log.getUserId());
        
        // 计算用时（仅针对CONFIRM_CONTRACT操作类型）
        if (ActionTypeEnums.CONFIRM_CONTRACT.getCode().equals(log.getActionType())) {
            setDuration(dto, log);
        }
        
        // 解析ext_data
        parseExtData(dto, log.getExtData());
        
        return dto;
    }
    
    /**
     * 设置流程类型信息
     */
    private void setFlowTypeInfo(ContractOperationLogRespDTO dto, String flowType) {
        dto.setFlowTypeCode(flowType);
        for (WorkFlowTypeEnums enumValue : WorkFlowTypeEnums.values()) {
            if (enumValue.getCode().equals(flowType)) {
                dto.setFlowTypeDesc(enumValue.getMsg());
                break;
            }
        }
    }
    
    /**
     * 设置操作类型信息
     */
    private void setActionTypeInfo(ContractOperationLogRespDTO dto, String actionType) {
        dto.setActionTypeCode(actionType);
        for (ActionTypeEnums enumValue : ActionTypeEnums.values()) {
            if (enumValue.getCode().equals(actionType)) {
                dto.setActionTypeDesc(enumValue.getMsg());
                break;
            }
        }
    }
    
    /**
     * 设置数据源类型信息
     */
    private void setSourceTypeInfo(ContractOperationLogRespDTO dto, String sourceType) {
        dto.setSourceTypeCode(sourceType);
        for (SourceTypeEnums enumValue : SourceTypeEnums.values()) {
            if (enumValue.getCode().equals(sourceType)) {
                dto.setSourceTypeDesc(enumValue.getMsg());
                break;
            }
        }
    }
    
    /**
     * 设置操作人信息
     */
    private void setOperatorInfo(ContractOperationLogRespDTO dto, Long userId) {
        if (userId == null) {
            return;
        }
        
        try {
            SysUser user = sysUserService.getById(userId);
            if (user != null) {
                ContractOperationLogRespDTO.OperatorInfo operator = new ContractOperationLogRespDTO.OperatorInfo();
                operator.setId(userId);
                operator.setName(user.getRealName());
                operator.setAvatar(user.getAvatar());
                dto.setOperator(operator);
            }
        } catch (Exception e) {
            log.error("获取操作人信息失败，用户ID: {}", userId, e);
        }
    }
    
    /**
     * 计算用时
     */
    private void setDuration(ContractOperationLogRespDTO dto, ContractOperationLog operationLog) {
        try {
            // 查询协商实例
            ContractNegotiationInstanceEntity instance = instanceMapper.selectOne(
                    new LambdaQueryWrapper<ContractNegotiationInstanceEntity>()
                            .eq(ContractNegotiationInstanceEntity::getContractId, operationLog.getContractId())
                            .orderByDesc(ContractNegotiationInstanceEntity::getCreatedAt)
                            .last("LIMIT 1")
            );
            
            if (instance == null) {
                return;
            }
            
            // 查询用户参与的节点实例
            ContractNegotiationParticipantEntity participant = participantMapper.selectOne(
                    new LambdaQueryWrapper<ContractNegotiationParticipantEntity>()
                            .eq(ContractNegotiationParticipantEntity::getInstanceId, instance.getId())
                            .eq(ContractNegotiationParticipantEntity::getEmployeeId, operationLog.getUserId())
                            .last("LIMIT 1")
            );
            
            if (participant == null || participant.getNodeInstanceId() == null) {
                return;
            }
            
            // 查询节点实例
            ContractNegotiationNodeInstanceEntity nodeInstance = nodeInstanceMapper.selectById(participant.getNodeInstanceId());
            if (nodeInstance == null || nodeInstance.getStartTime() == null || nodeInstance.getFinishTime() == null) {
                return;
            }
            
            // 计算用时
            Duration duration = Duration.between(nodeInstance.getStartTime(), nodeInstance.getFinishTime());
            dto.setDuration(formatDuration(duration));
            
        } catch (Exception e) {
            log.error("计算用时失败，操作日志ID: {}", operationLog.getId(), e);
        }
    }
    
    /**
     * 格式化用时
     */
    private String formatDuration(Duration duration) {
        long days = duration.toDays();
        long hours = duration.toHours() % 24;
        long minutes = duration.toMinutes() % 60;
        
        if (days > 0) {
            return String.format("%d天%d小时%d分钟", days, hours, minutes);
        } else if (hours > 0) {
            return String.format("%d小时%d分钟", hours, minutes);
        } else {
            return String.format("%d分钟", Math.max(1, minutes)); // 至少显示1分钟
        }
    }
    
    /**
     * 解析ext_data
     */
    private void parseExtData(ContractOperationLogRespDTO dto, String extData) {
        if (extData == null || extData.trim().isEmpty()) {
            return;
        }
        
        try {
            Map<String, Object> dataMap = JSON.parseObject(extData, Map.class);
            
            // 解析主合同文件ID
            if (dataMap.containsKey("mainContractFileId")) {
                Object fileIdObj = dataMap.get("mainContractFileId");
                if (fileIdObj != null) {
                    String fileId = fileIdObj.toString();
                    parseMainContractFile(dto, fileId);
                }
            }
            
            // 解析协商者ID列表
            if (dataMap.containsKey("participantIds")) {
                Object participantIdsObj = dataMap.get("participantIds");
                if (participantIdsObj instanceof List) {
                    @SuppressWarnings("unchecked")
                    List<String> participantIds = (List<String>) participantIdsObj;
                    parseNegotiators(dto, participantIds);
                }
            }
            
            // 解析版本信息
            if (dataMap.containsKey("version")) {
                Object versionObj = dataMap.get("version");
                if (versionObj != null) {
                    dto.setVersion(versionObj.toString());
                }
            }
            
        } catch (Exception e) {
            log.error("解析ext_data失败，数据: {}", extData, e);
        }
    }
    
    /**
     * 解析主合同文件
     */
    private void parseMainContractFile(ContractOperationLogRespDTO dto, String fileId) {
        try {
            SingleResponse<FileVO> fileResult = fileInfoService.getFileInfoById(fileId);
            if (fileResult.isSuccess() && fileResult.getData() != null) {
                dto.setMainContractFile(fileResult.getData());
            }
        } catch (Exception e) {
            log.error("获取主合同文件信息失败，文件ID: {}", fileId, e);
        }
    }
    
    /**
     * 解析协商者
     */
    private void parseNegotiators(ContractOperationLogRespDTO dto, List<String> participantIds) {
        if (participantIds == null || participantIds.isEmpty()) {
            return;
        }
        
        try {
            List<ContractOperationLogRespDTO.NegotiatorInfo> negotiators = new ArrayList<>();
            
            for (String participantIdStr : participantIds) {
                try {
                    Long participantId = Long.parseLong(participantIdStr);
                    SysUser user = sysUserService.getById(participantId);
                    if (user != null) {
                        ContractOperationLogRespDTO.NegotiatorInfo negotiator = 
                                new ContractOperationLogRespDTO.NegotiatorInfo();
                        negotiator.setId(participantId);
                        negotiator.setName(user.getRealName());
                        negotiator.setAvatar(user.getAvatar());
                        negotiators.add(negotiator);
                    }
                } catch (NumberFormatException e) {
                    log.warn("解析协商者ID失败: {}", participantIdStr);
                }
            }
            
            dto.setNegotiators(negotiators);
            
        } catch (Exception e) {
            log.error("解析协商者失败，参与者ID列表: {}", participantIds, e);
        }
    }
} 